package com.rbs.service.impl;

import com.rbs.entity.AuctionRecord;
import com.rbs.dao.AuctionRecordMapper;
import com.rbs.service.IAuctionRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author rbs
 * @since 2022-04-29
 */
@Service
public class AuctionRecordServiceImpl extends ServiceImpl<AuctionRecordMapper, AuctionRecord> implements IAuctionRecordService {
    @Resource
    //获取redisTemplate工具
    private RedisTemplate<String,Object> redisTemplate;
    @Override
    public void checkAndSave(AuctionRecord ar) {
        //生成不重复的uuid
        String uuid = UUID.randomUUID().toString();
        try {
            //判断redis里边是否有lock锁标记,没有就放入
            Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 10, TimeUnit.SECONDS);
            //没有 进行功能插入
            if (lock){
                Integer auctionId = ar.getAuctionId();
                //根据id获取当前最大价格
                Double maxPrice = baseMapper.selectMaxPriceByAuctionId(auctionId);
                //比较当前价格是否是最大价格
                Double recordPrice = ar.getRecordPrice();
                if (recordPrice>maxPrice){
                    this.save(ar);
                }else {
                    throw new RuntimeException("当前价格低于最高价格");
                }
            }else {//有锁标记 等待
                try {
                    Thread.sleep(100);//睡眠100毫秒
                    checkAndSave(ar);//再尝试拿锁标记
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }finally {
            //查询完成解锁
            String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end";
            /**
             * 参数1 脚本
             * 参数2 要删除的key
             * 参数3 uuid
             */
            redisTemplate.execute(
                    new DefaultRedisScript<Long>(script,Long.class),
                    Arrays.asList("redis-lock"),
                    uuid
            );
        }
    }
}
